﻿using System;
using System.Data;
using System.Linq;
using FrameWork.Language;
using System.ComponentModel;
using System.Collections.Generic;

namespace FrameWork.Npoi.Helper
{
    /// <summary>
    /// 导出助手
    /// </summary>
    public class ExportHelper
    {
        /// <summary>
        /// 导出数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <param name="title"></param>
        /// <param name="propertNames"></param>
        /// <param name="items"></param>
        /// <exception cref="Exception">导出失败</exception>
        public static void Export<T>(string path, string title, IEnumerable<string> propertNames, IEnumerable<T> items)
        {
            string localFilePath = path;
            var dt = ToDataTable(items, propertNames);
            ExcelHelper helper = new XSSFExcelHelper();
            helper.Add(title, dt);
            helper.ReportClient(localFilePath);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="propertNames"></param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(IEnumerable<T> list, IEnumerable<string> propertNames)
        {
            DataTable table = new DataTable();
            var props = TypeDescriptor.GetProperties(typeof(T)).Sort(propertNames.ToArray());
            var exportPorps = new Dictionary<string, PropertyDescriptor>();
            for (int i = 0; i < props.Count; i++)
            {
                PropertyDescriptor prop = props[i];
                if (!propertNames.Contains(prop.Name)) continue;

                var colName = I18n.Get(prop.Description);
                foreach (var att in prop.Attributes)
                {
                    if (att is RequiredAttribute)
                    {
                        colName = $"{colName}*";
                        break;
                    }
                }
                table.Columns.Add(colName, ((prop.PropertyType.IsEnum || prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?)) ? typeof(string) : (Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType)));
                exportPorps.Add(prop.Name, prop);
            }
            object[] values = new object[exportPorps.Count];
            foreach (T item in list)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    var prop = exportPorps.ElementAt(i).Value;
                    var val = prop.GetValue(item);
                    if (prop.PropertyType.IsEnum)
                        values[i] = I18n.Get(((Enum)val).GetDescription(),"enum");
                    else if(prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?))
                    {
                        DateTimeFormatAttribute fAtt = null;
                        foreach (var att in prop.Attributes)
                        {
                            if (att is DateTimeFormatAttribute)
                            {
                                fAtt = att as DateTimeFormatAttribute;
                                break;
                            }
                        }
                        if (fAtt == null)
                            values[i] = val ?? DBNull.Value;
                        else
                            values[i] = val == null ? "" : ((DateTime)val).ToString(fAtt.Format);
                    }
                    else
                        values[i] = val ?? DBNull.Value;
                }

                table.Rows.Add(values);
            }
            return table;
        }

        /// <summary>
        /// 导出数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <param name="title"></param>
        /// <param name="propertNames"></param>
        /// <param name="items"></param>
        /// <exception cref="Exception">导出失败</exception>
        public static void ExportEx(string path, string title, IEnumerable<string> propertNames, IEnumerable<dynamic> items)
        {
            string localFilePath = path;
            var dt = ToDataTableEx(items, propertNames);
            ExcelHelper helper = new XSSFExcelHelper();
            helper.Add(title, dt);
            helper.ReportClient(localFilePath);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="propertNames"></param>
        /// <returns></returns>
        public static DataTable ToDataTableEx(IEnumerable<dynamic> list, IEnumerable<string> propertNames)
        {
            DataTable table = new DataTable();
            foreach (var pn in propertNames)
            {
                table.Columns.Add(pn);
            }
            foreach (var item in list)
            {
                var dic = (IDictionary<string, object>)item;
                var values = dic.Select(p => p.Value).ToArray();
                table.Rows.Add(values);
            }


            //foreach (var rows in list.Take(1))
            //{
            //    var column = rows as IDictionary<string, object>;
               
            //    for (int i = 1; i < column.Keys.Count; i++)
            //    {
            //        table.Columns.Add(column.Keys.ElementAt(i), (i==1 ? typeof(string) : typeof(int)));
            //    }
            //    object[] values = new object[column.Keys.Count - 1];          
            //    foreach (T item in list)
            //    {
            //        var value = (IDictionary<string, object>)item;
            //        for (int j = 1; j < value.Values.Count; j++)
            //        {
            //            var prop = j != 1 ? value.Values.ElementAt(j) : String.Format("{0:yyyy-MM-dd}", value.Values.ElementAt(j));
            //            values[j - 1] = prop ?? DBNull.Value;
            //        }
            //        table.Rows.Add(values);                    
            //    }
            //}
            return table;
        }
    }
}
